<script setup lang="ts">
import { ArrowDown, Delete, InfoFilled, Plus } from '@element-plus/icons-vue'
import YkTableColumn from '@yk/components/table-column/YkTableColumn.vue'
import { ObjectUtil } from '@utils/object-util'
import { ElForm, ElInput, ElTable, UploadUserFile } from 'element-plus'
import YkUploadFile from '@yk/components/upload/upload-file/YkUploadFile.vue'
import { VariableDTO, VariableModelSaveForm, VariableSaveForm } from '@/api/entity/variable'
import { ElValidator, positiveIntegerRule, required } from '@utils/form-rule'
import { TabBarUtil } from '@/layout/components/tab-bar'
import { addVariableModelAPI, editVariableModelAPI, getVariableModelByIdAPI } from '@/api/variable'
import { decrypt, encrypt } from '@utils/crypto'
import { FileUtil } from '@/utils'
import { XLSXUtil } from '@utils/xlsx'

const route = useRoute()
// 只读的
const isReadOnly = shallowRef(false)

/**
 * 支持query参数
 * @param id 【回显必填】-回显数据
 * 支持params
 * @param defaultValue 网关生成的简易变量
 * defaultValue: { id: string, address: string[], name: string }
 */
let routeParams = {} as {
  defaultValue?: { id: string, address: string[], name: string }
}
onMounted(() => {
  routeParams = route.params
  loadSaveFormRef()
  if (['CheckVariableTemplate', 'EditVariableTemplate'].includes(route.name as string)) {
    getVariableModelData()
    if (route.name === 'CheckVariableTemplate') {
      isReadOnly.value = true
    }
  } else if (route.name === 'AddVariableTemplate' && routeParams.defaultValue) {
    loadGatewayVariable()
  }
})

// region TODO 数据回显
function getVariableModelData () {
  const loading = ElLoading.service()
  getVariableModelByIdAPI({ id: route.query.id.toString() }).then((res) => {
    res.result().then((rdata) => {
      const data = rdata.data
      variableModelSaveForm.value = new VariableModelSaveForm({
        id: data.id,
        modelName: data.modelName,
        vbVariableDTOS: data.vbVariableDTOS?.map(item => new VariableSaveForm(item))
      })
      // 如果携带了网关生成的简易变量
      if (routeParams.defaultValue) {
        loadGatewayVariable()
      }
    })
  }).finally(loading.close)
}
// endregion

// region TODO 查询
// endregion

// region TODO 表格
const tableDataRef = ref<InstanceType<typeof ElTable>>()
// endregion

// region TODO 添加/修改表单

const variableModelSaveForm = ref(new VariableModelSaveForm())
const variableModelSaveFormRules = {
  modelName: [required('模板名称为必填项')]
}
const variableModelSaveFormRef = shallowRef<InstanceType<typeof ElForm>>()
function submitVariableModelSaveFormHandle () {
  variableModelSaveFormRef.value.validate().then(() => {
    const params = variableModelSaveForm.value
    const loading = ElLoading.service()
    const result = variableModelSaveForm.value.id ? editVariableModelAPI(params) : addVariableModelAPI(params)
    result.then((res) => {
      res.result().then(() => {
        ElMessage.success('保存成功')
        const name = route.name
        TabBarUtil.value.open({ name: 'VariableTemplate' }).then(() => {
          TabBarUtil.value.close(name as string)
        })
      })
    }).finally(loading.close)
  })
}
// endregion

// region TODO 添加/修改变量表单
// region TODO 表单
const editTableItemIndex = ref(null)
const saveForm = ref(new VariableSaveForm())

// 数据修正规则
const formulaRule: ElValidator = {
  validator (rule: any, value: any, callback: (error?: Error) => void) {
    callback(ObjectUtil.isEmpty(value) || /^(?=.*X)((\d+(.\d+)?)|[+\-*/()X])+$/.test(value) ? undefined : Error('公式中只能包含 数字 X + - * / ( )且必须包含X'))
  },
  trigger: 'blur'
}
const saveFormRules = {
  // 变量类型 0-模拟量 1-开关量
  type: [required('变量类型为必填项')],
  // 变量名称
  name: [required('变量名称为必填项')],
  // 变量地址
  address: [required('变量地址为必填项'), {
    validator (rule: any, value: any, callback: (error?: Error) => void) {
      const result = variableModelSaveForm.value.vbVariableDTOS.some((item, index) => {
        return editTableItemIndex.value !== index && item.address === value
      })
      callback(result ? Error('变量地址已使用') : undefined)
    },
    trigger: 'blur'
  } as ElValidator],
  // 数据修正
  formula: [formulaRule],
  // 写数据修正
  writeFormula: [formulaRule],
  // 代表状态
  indicatesStatus: [{
    validator (rule: any, value: any, callback: (error?: Error) => void) {
      const indicatesStatus = saveForm.value.indicatesStatus
      if (indicatesStatus.length < 2) {
        callback(Error('代表状态最少应有两项'))
        return
      }
      if (indicatesStatus.some(item => ObjectUtil.isEmpty(item.statusName) || ObjectUtil.isEmpty(item.statusValue))) {
        callback(Error('键与值均不可为空'))
        return
      }
      if (new Set(indicatesStatus.map(item => item.statusName)).size < indicatesStatus.length) {
        callback(Error('存在相同的键值'))
        return
      }
      callback(undefined)
    },
    trigger: 'change',
    required: true
  } as ElValidator],
  // 小数位
  decimal: [required('保留小数位为必填项')],
  // 是否展示 0-不展示 1-展示
  show: [required('是否展示为必填项')],
  // 是否存储 0-不存储 1-存储
  storage: [required('历史存储为必填项'), {
    validator (rule: any, value: any, callback: (error?: Error) => void) {
      // 因为差值变量必须是存储变量，校验是否被差值变量使用
      if (value === '0' && getDifferenceValueOccupy().has(saveForm.value.address)) {
        callback(Error('变量被差值变量使用，必须为存储变量'))
        return
      }
      callback(undefined)
    },
    trigger: 'blur'
  } as ElValidator],
  // 是否控制 0-不控制 1-控制
  control: [required('是否控制为必填项')],
  // 读取最大值（最大有效值）
  readMax: [{
    validator (rule: any, value: any, callback: (error?: Error) => void) {
      const { readMin, readMax } = saveForm.value
      if (ObjectUtil.isNotEmpty(readMax) && ObjectUtil.isNotEmpty(readMin) && readMax < readMin) {
        callback(Error('最大有效值不能小于最小有效值'))
        return
      }
      callback(undefined)
    },
    trigger: 'blur'
  } as ElValidator],
  // 读取最小值（最小有效值）
  readMin: [{
    validator (rule: any, value: any, callback: (error?: Error) => void) {
      const { readMin, readMax } = saveForm.value
      if (ObjectUtil.isNotEmpty(readMax) && ObjectUtil.isNotEmpty(readMin) && readMin > readMax) {
        callback(Error('最小有效值不能大于最大有效值'))
        return
      }
      callback(undefined)
    },
    trigger: 'blur'
  } as ElValidator],
  // 写入最大值
  writeMax: [{
    validator (rule: any, value: any, callback: (error?: Error) => void) {
      const { writeMax, writeMin, readMax } = saveForm.value
      if (ObjectUtil.isNotEmpty(writeMax) && ObjectUtil.isNotEmpty(writeMin) && writeMax < writeMin) {
        callback(Error('可写最大值不能小于可写最小值'))
        return
      }
      if (ObjectUtil.isNotEmpty(readMax) && writeMax > readMax) {
        callback(Error('可写最大值不能大于最大有效值'))
        return
      }
      callback(undefined)
    },
    trigger: 'blur'
  } as ElValidator],
  // 写入最小值
  writeMin: [{
    validator (rule: any, value: any, callback: (error?: Error) => void) {
      const { writeMax, writeMin, readMin } = saveForm.value
      if (ObjectUtil.isNotEmpty(writeMax) && ObjectUtil.isNotEmpty(writeMin) && writeMax < writeMin) {
        callback(Error('可写最小值不能大于可写最大值'))
        return
      }
      if (ObjectUtil.isNotEmpty(readMin) && writeMin < readMin) {
        callback(Error('可写最小值不能小于最小有效值'))
        return
      }
      callback(undefined)
    },
    trigger: 'blur'
  } as ElValidator],
  // 计算类型
  computeType: [required.change('计算方式为必填项')],
  // 引用变量地址
  parentAddress: [required.change('源变量为必填项')],
  // 周期频率 0-日 1-周 2-月
  cycleFrequency: [required('周期频率为必填项')],
  // 是否复位 0-否 2-是
  reset: [required('是否复位为必填项')],
  // 复位时间（秒）
  resetTime: [required('复位延迟为必填项'), positiveIntegerRule],
  // 复位指令
  resetCommand: [required('复位指令为必填项')]
}

// 关闭并返回
function closeAndBack () {
  if (isReadOnly.value) {
    TabBarUtil.value.close(route.name)
  } else {
    ElMessageBox.confirm('确认放弃修改当前变量配置', '取消提醒').then(() => {
      TabBarUtil.value.close(route.name)
    })
  }
}

// region TODO 加载 saveFormRef
const isLoadSaveFormRef = shallowRef(false)
// 因为不打开抽屉不渲染Form，模拟打打开抽屉。为避免遮罩层闪屏，临时关闭遮罩层
function loadSaveFormRef () {
  isLoadSaveFormRef.value = true
  saveFormDrawerModel.value = true
  nextTick(() => {
    saveFormDrawerModel.value = false
    setTimeout(() => {
      isLoadSaveFormRef.value = false
    }, 500)
  })
}
// endregion
// endregion

// region TODO 代表状态
const positionStickyRef = shallowRef<HTMLDivElement>()
function addIndicatesStatusItem () {
  saveForm.value.indicatesStatus.push({ statusName: null, statusValue: '', colour: '#1570BB' })
  nextTick(() => {
    positionStickyRef.value.scrollTo({
      top: positionStickyRef.value.scrollHeight,
      behavior: 'smooth'
    })
  })
}
function delIndicatesStatusItem (index: number) {
  saveForm.value.indicatesStatus.splice(index, 1)
}
// endregion

// region TODO 抽屉 - 通用
// 关闭当前抽屉 - 通用
function closeSaveFormDrawerGeneral () {
  const closeDrawerDic = {
    // 普通变量
    0: () => closeSaveFormDrawer(),
    // 差值变量
    1: () => closeDifferenceValueVariableDrawer(),
    // 计算变量
    2: () => closeComputeVariableDrawer()
  }
  closeDrawerDic[saveForm.value.dataType]()
}

// 打开抽屉 - 通用 - 编辑
function openSaveFormDrawerGeneral (item: VariableSaveForm, index: number) {
  const showDrawerDic = {
    // 普通变量
    0: () => { showSaveFormDrawer(item, index) },
    // 差值变量
    1: () => { showDifferenceValueVariableDrawer(item, index) },
    // 计算变量
    2: () => { showComputeVariableDrawer(item, index) }
  }
  showDrawerDic[item.dataType]()
}

// 提交变量表单 - 通用 - 编辑
function submitSaveVariableFormGeneral (options?: { to: number }) {
  ({
    // 普通变量
    0: submitSaveFormHandle,
    // 差值变量
    1: differenceValueSubmitSaveFormHandle,
    // 计算变量
    2: computeVariableSubmitSaveFormHandle
  })[saveForm.value.dataType](false).then(() => {
    let index = editTableItemIndex.value + options.to
    const varCount = variableModelSaveForm.value.vbVariableDTOS.length
    if (index >= varCount) index = 0
    else if (index < 0) index = varCount - 1
    const item = variableModelSaveForm.value.vbVariableDTOS[index]
    if (saveForm.value.dataType !== item.dataType) {
      closeSaveFormDrawerGeneral()
    }
    openSaveFormDrawerGeneral(item, index)
  })
  // _submitSaveFormValidate().then(() => {
  //   // 编辑
  //   if (ObjectUtil.isNotEmpty(editTableItemIndex.value)) {
  //     if (!isContinue) closeSaveFormDrawerGeneral()
  //     else {
  //       let index = editTableItemIndex.value + options.to
  //       const varCount = variableModelSaveForm.value.vbVariableDTOS.length
  //       if (index >= varCount) index = 0
  //       else if (index < 0) index = varCount - 1
  //
  //       const item = variableModelSaveForm.value.vbVariableDTOS[index]
  //       if (saveForm.value.dataType !== item.dataType) {
  //         closeSaveFormDrawerGeneral()
  //       }
  //       openSaveFormDrawerGeneral(item, index)
  //     }
  //   } else {
  //     if (!isContinue) closeSaveFormDrawerGeneral()
  //     else {
  //       saveForm.value.address = ''
  //     }
  //   }
  // })
}
// endregion

// region TODO 普通变量 - 抽屉
const saveFormDrawerModel = ref(false)
const saveFormRef = shallowRef<InstanceType<typeof ElForm>>()
function showSaveFormDrawer (item?: VariableSaveForm, index?: number) {
  saveFormDrawerModel.value = true
  nextTick(() => {
    setSaveForm(item, index)
  })
}
function closeSaveFormDrawer () {
  saveFormDrawerModel.value = false
  saveFormRef.value.resetFields()
  saveForm.value.id = null
  editTableItemIndex.value = null
}

// 设置表单
function setSaveForm (item: VariableSaveForm, index?: number) {
  if (item) {
    editTableItemIndex.value = index
    saveForm.value = ObjectUtil.copy(item)
  } else {
    saveForm.value = new VariableSaveForm()
  }
  if (!saveForm.value.indicatesStatus?.length) {
    saveForm.value.indicatesStatus = [
      { statusName: 0, statusValue: '关', colour: '#1570BB' },
      { statusName: 1, statusValue: '开', colour: '#1570BB' }
    ]
  }
}
function submitSaveFormHandle (closeDrawer = true) {
  const result = saveFormRef.value.validate()
  result.then(() => {
    const tableDataItem = ObjectUtil.copy(saveForm.value)
    // 清除副作用
    if (tableDataItem.type === '0') { // 模拟量
      tableDataItem.indicatesStatus = []
    } else {
      tableDataItem.decimal = null
      tableDataItem.formula = null
      tableDataItem.unit = null
    }
    // 编辑
    if (ObjectUtil.isNotEmpty(editTableItemIndex.value)) {
      variableModelSaveForm.value.vbVariableDTOS[editTableItemIndex.value] = tableDataItem
    } else {
      variableModelSaveForm.value.vbVariableDTOS.push(ObjectUtil.copy(tableDataItem))
    }
    closeDrawer && closeSaveFormDrawer()
  })
  return result
}
// 继续添加
function submitSaveFormHandleContinue () {
  submitSaveFormHandle(false).then(() => {
    saveForm.value.address = ''
  })
}
// endregion

// region TODO 差值变量 - 抽屉
const differenceValueSaveFormRef = shallowRef<InstanceType<typeof ElForm>>()
const differenceValueVariableDialogModel = ref(false)
// 源变量
const differenceValueVariableList = shallowRef<VariableDTO[]>([])
function showDifferenceValueVariableDrawer (item?: VariableSaveForm, index?: number) {
  differenceValueVariableDialogModel.value = true
  editTableItemIndex.value = index
  const vbVariableDTOS = variableModelSaveForm.value.vbVariableDTOS
  differenceValueVariableList.value = vbVariableDTOS.filter(item => item.dataType === '0')
  nextTick(() => {
    if (!item) {
      item = new VariableSaveForm({
        type: '0', // 差值变量只能是模拟量
        dataType: '1'
      })
    }
    saveForm.value = ObjectUtil.copy(item)
  })
}
function closeDifferenceValueVariableDrawer () {
  differenceValueVariableDialogModel.value = false
  differenceValueSaveFormRef.value.resetFields()
  saveForm.value.id = null
}
function differenceValueSubmitSaveFormHandle (closeDrawer = true) {
  const result = differenceValueSaveFormRef.value.validate()
  result.then(async () => {
    const sourceVariable = getVariableByAddress(saveForm.value.parentAddress)
    // 如果你选中的变量不是存储变量
    if (sourceVariable.storage === '0') {
      try {
        await ElMessageBox.confirm('当前源变量不是存储变量，差值变量需要源变量为存储变量，是否修改源变量为存储变量？')
        sourceVariable.storage = '1'
      } catch (e) {
        return
      }
    }
    const tableDataItem = ObjectUtil.copy(saveForm.value)
    // 清除副作用
    if (tableDataItem.computeType === '1') tableDataItem.cycleFrequency = ''
    // 编辑
    if (ObjectUtil.isNotEmpty(editTableItemIndex.value)) {
      variableModelSaveForm.value.vbVariableDTOS[editTableItemIndex.value] = tableDataItem
    } else {
      variableModelSaveForm.value.vbVariableDTOS.push(ObjectUtil.copy(tableDataItem))
    }
    closeDrawer && closeDifferenceValueVariableDrawer()
  })
  return result
}
// endregion

// region TODO 计算变量 - 抽屉
const computeVariableSaveFormRef = shallowRef<InstanceType<typeof ElForm>>()
const computeVariableDialogModel = ref(false)
const computeVariableFormRules = shallowRef({
  source: [
    {
      validator (rule: any, value: any, callback: (error?: Error) => void) {
        callback(computeVariableSource.value.length < 2 ? Error('源变量最少选择两个') : undefined)
      },
      trigger: 'change',
      required: true
    } as ElValidator
  ],
  formula: [
    // required('计算公式必填项'),
    {
      validator (rule: any, value: any, callback: (error?: Error) => void) {
        let _formula = saveForm.value.formula ??= ''
        computeVariableSourceDicList.value.forEach(item => {
          _formula = _formula.replaceAll(item.key, '1')
        })

        try {
          // eslint-disable-next-line no-eval
          callback(isNaN(eval(_formula)) ? Error('公式可能有误，请检查公式') : undefined)
        } catch (e) {
          callback(Error('公式可能有误，请检查公式'))
        }
      },
      required: true,
      trigger: 'blur'
    } as ElValidator]
})
// 计算公式输入框
const computeVariableFormulaRef = shallowRef<InstanceType<typeof ElInput>>()
// 源变量列表
const computeVariableList = shallowRef<VariableDTO[]>([])
const computeVariableListDic = shallowRef<Record<string, VariableDTO>>({})
// 源变量 - 临时存储
const computeVariableSource = ref<string[]>([])

// region TODO 变量字典 Tag
const computeVariableSourceKeys = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K']
// 页面变量字典Tag列表
type ComputeVariableSourceDicListType = { key: string, address: string, name: string }
const computeVariableSourceDicList = shallowRef<ComputeVariableSourceDicListType[]>([])
watch(() => computeVariableSource.value, (nv) => {
  const keysSet = new Set(computeVariableSourceKeys)
  const tagDic = computeVariableSourceDicList.value.reduce<Record<string, ComputeVariableSourceDicListType>>((ret, item) => {
    ret[item.address] = item
    keysSet.delete(item.key)
    return ret
  }, {})
  computeVariableSourceDicList.value = nv.map(address => {
    // 如果已存在
    if (tagDic[address]) {
      return tagDic[address]
    } else {
      const variable = computeVariableListDic.value[address]
      const keys = Array.from(keysSet)
      keysSet.delete(keys[0])
      return { key: keys[0], address, name: variable.name }
    }
  })
}, { deep: true })

// 关闭Tag
function computeVariableCloseTag (index: number) {
  computeVariableSource.value.splice(index, 1)
}
// Tag点击事件
function computeVariableTagClick (item: ComputeVariableSourceDicListType) {
  saveForm.value.formula ??= ''
  saveForm.value.formula += item.key
  computeVariableFormulaRef.value.focus()
}

// endregion

function showComputeVariableDrawer (item?: VariableSaveForm, index?: number) {
  computeVariableDialogModel.value = true
  editTableItemIndex.value = index
  // 获取源变量
  const vbVariableDTOS = variableModelSaveForm.value.vbVariableDTOS
  computeVariableListDic.value = {}
  computeVariableList.value = vbVariableDTOS.filter(item => {
    if (item.dataType === '0') {
      computeVariableListDic.value[item.address] = item
      return true
    } else {
      return false
    }
  })

  nextTick(() => {
    if (!item) {
      item = new VariableSaveForm({
        type: '0', // 计算变量只能是模拟量
        dataType: '2'
      })
    }
    // 回显数据
    const _computeVariableSourceDicList = []
    const addressList = []
    for (const [key, address] of Object.entries(item.interior)) {
      addressList.push(address)
      _computeVariableSourceDicList.push({ key, address, name: computeVariableListDic.value[address]?.name })
    }
    computeVariableSourceDicList.value = _computeVariableSourceDicList
    computeVariableSource.value = addressList

    saveForm.value = ObjectUtil.copy(item)
  })
}
function closeComputeVariableDrawer () {
  computeVariableDialogModel.value = false
  saveFormRef.value.resetFields()
  saveForm.value.id = null
  computeVariableSource.value = []
}
function computeVariableSubmitSaveFormHandle () {
  computeVariableSaveFormRef.value.validate().then(async () => {
    const tableDataItem = ObjectUtil.copy(saveForm.value)
    tableDataItem.interior = computeVariableSourceDicList.value.reduce((ret, item) => {
      ret[item.key] = item.address
      return ret
    }, {})
    // 编辑
    if (ObjectUtil.isNotEmpty(editTableItemIndex.value)) {
      variableModelSaveForm.value.vbVariableDTOS[editTableItemIndex.value] = tableDataItem
    } else {
      variableModelSaveForm.value.vbVariableDTOS.push(ObjectUtil.copy(tableDataItem))
    }
    closeComputeVariableDrawer()
  })
}
// endregion

// endregion

// region TODO 查询Utils
// region TODO 获取占用变量
// 获取被计算变量（复合变量、差值变量等非普通变量）占用的普通变量
function getOccupyNormalVariable () {
  return getDifferenceValueOccupy()
}

// 获取差值变量占用的变量
function getDifferenceValueOccupy () {
  return variableModelSaveForm.value.vbVariableDTOS.reduce((ret, item) => {
    if (item.dataType === '1') {
      ret.add(item.parentAddress)
    }
    return ret
  }, new Set())
}
// endregion

// 根据变量地址获取变量
function getVariableByAddress (address: string): VariableSaveForm {
  return variableModelSaveForm.value.vbVariableDTOS.find(item => item.address === address)
}
// endregion

// region TODO 删除
function delVariableItem (index: number) {
  const variable = variableModelSaveForm.value.vbVariableDTOS[index]
  // 如果删除的是普通变量
  if (['0', '1'].includes(variable.dataType)) {
    if (getOccupyNormalVariable().has(variable.address)) {
      ElMessage.warning('当前变量被引用无法删除')
      return
    }
  }
  const message = `确认要删除变量 ${variable.name}(${variable.address}) 吗？`
  if (variable.id) {
    ElMessageBox.confirm(message + '它当前正在使用', '删除提醒').then(() => {
      variableModelSaveForm.value.variableIds.push(variable.id)
      variableModelSaveForm.value.vbVariableDTOS.splice(index, 1)
    })
  } else {
    ElMessageBox.confirm(message, '删除提醒').then(() => {
      variableModelSaveForm.value.vbVariableDTOS.splice(index, 1)
    })
  }
}

function batchDelVariableItem () {
  const rows = tableDataRef.value.getSelectionRows()
  if (!rows.length) {
    ElMessage.info('请勾选需要删除的变量')
    return
  }
  // 存在数据库的，正在使用的变量
  const oldVariable = []
  // 刚刚添加的，还没保存到的
  const newVariable = []
  rows.forEach((row: VariableSaveForm) => {
    if (row.id) {
      oldVariable.push(row)
    } else {
      newVariable.push(row)
    }
  })
  // 如果都是新变量
  if (newVariable.length && !oldVariable.length) {
    ElMessageBox.confirm(`确认要删除当前所选的${rows.length}个变量吗？`).then(() => {
      batchDelVariableItemHandle(rows)
    })
  } else if (oldVariable.length && !newVariable.length) { // 如果都是老变量
    ElMessageBox.confirm(`确认要删除当前所选的${rows.length}个变量吗？它们仍在使用中`).then(() => {
      batchDelVariableItemHandle(rows)
    })
  } else {
    ElMessageBox.confirm(`确认要删除当前所选的${rows.length}个变量吗？其中${oldVariable.length}仍在使用中`, {
      distinguishCancelAndClose: true,
      confirmButtonText: '全部删除',
      cancelButtonText: '仅删除本地变量'
    }).then(() => {
      batchDelVariableItemHandle(rows)
    }).catch((e) => {
      if (e === 'cancel') {
        batchDelVariableItemHandle(newVariable)
      }
    })
  }
}
function batchDelVariableItemHandle (delRow: VariableSaveForm[]) {
  /**
   * 先把需要产出的计算变量删除，然后找到剩余被引用的普通变量，删除没有被引用的普通变量，提示被引用的普通变量
   */
  // 存储普通变量
  const normalVariable: VariableSaveForm[] = []
  // 存储计算变量
  const computeVariable: VariableSaveForm[] = []

  delRow.forEach(item => {
    if (item.dataType === '0') normalVariable.push(item)
    else computeVariable.push(item)
  })
  _batchDelVariableItem(computeVariable)
  // 允许删除的变量
  const permitDelRow: VariableSaveForm[] = []
  // 不允许删除的变量
  const notPermitDelRow: VariableSaveForm[] = []
  // 获取被占用的普通变量
  const occupyVariable = getOccupyNormalVariable()

  normalVariable.forEach(item => {
    if (occupyVariable.has(item.address)) notPermitDelRow.push(item)
    else permitDelRow.push(item)
  })

  _batchDelVariableItem(permitDelRow)

  if (notPermitDelRow.length) {
    ElMessageBox.alert(`${notPermitDelRow.length}个普通变量没有被删除，它们仍在被引用。未删除的变量有${notPermitDelRow.map(item => item.name).join('，')}`)
  }
}
function _batchDelVariableItem (delRow: VariableSaveForm[]) {
  const dataset = new Set(variableModelSaveForm.value.vbVariableDTOS)
  for (let i = 0, len = delRow.length; i < len; i++) {
    dataset.delete(delRow[i])
    if (delRow[i].id) variableModelSaveForm.value.variableIds.push(delRow[i].id)
  }
  variableModelSaveForm.value.vbVariableDTOS = Array.from(dataset)
}
// endregion

// region TODO 排序
const sortTempData = ref([])
const isOpenSort = shallowRef(false)
watch(() => variableModelSaveForm.value.vbVariableDTOS.length, () => {
  isOpenSort.value && updateSortTempData()
}, { deep: false })
function openSort () {
  isOpenSort.value = true
  updateSortTempData()
}
function closeSort () {
  isOpenSort.value = false
  sortTempData.value = []
}
function updateSortTempData () {
  const len = variableModelSaveForm.value.vbVariableDTOS.length
  const temp = []
  for (let i = 0; i < len; i++) {
    temp[i] = i + 1
  }
  nextTick(() => {
    sortTempData.value = temp
  })
}

function sortBlurHandle (index: number) {
  const tableItem = variableModelSaveForm.value.vbVariableDTOS.splice(index, 1)
  variableModelSaveForm.value.vbVariableDTOS.splice(sortTempData.value[index] - 1, 0, ...tableItem)
  updateSortTempData()
}

// endregion

// region TODO JSON 导入导出
const uploadFile = shallowRef<UploadUserFile>()
function loadTableData (e: UploadUserFile) {
  uploadFile.value = null
  if (variableModelSaveForm.value.vbVariableDTOS.length) {
    ElMessage.info('当前已存在变量，请先删除已添加的变量')
    return
  }
  const reader = new FileReader()
  reader.readAsText(e.raw)
  reader.onload = (e) => {
    const optionStr = e.target.result as string
    try {
      const option = JSON.parse(optionStr) as {
        version: string, options: string
      }
      // ---- 校验版本是否兼容 当前仅有1.0.0，暂不做检验
      variableModelSaveForm.value.vbVariableDTOS = JSON.parse(decrypt(option.options))
    } catch (e) {
      ElMessage.warning('配置格式错误')
    }
  }
}
function exportTableData () {
  const _vbVariableDTOS = ObjectUtil.copy(variableModelSaveForm.value.vbVariableDTOS)
  _vbVariableDTOS.forEach((item) => delete item.id)
  const content = JSON.stringify({ version: '1.0.0', options: encrypt(JSON.stringify(_vbVariableDTOS)) })
  const fileName = '模板配置.json'
  const file = new File([content], fileName)
  FileUtil.downloadFile(file)
}
// endregion

// region TODO Excel 导入导出
const uploadExcelFile = shallowRef<UploadUserFile>()
// 导入
function loadExcelTableData (e: UploadUserFile) {
  uploadExcelFile.value = null
  const header = ['no', 'name', 'address', 'type', 'unit', 'formula', 'storage', 'show', 'control']
  XLSXUtil.readFileTo<VariableSaveForm>(e.raw, header).then(async (res) => {
    // 清理表头
    res.shift()
    const vbVariableDTOSDic = variableModelSaveForm.value.vbVariableDTOS.reduce((ret, item, index) => {
      ret[item.address] = { var: item, index }
      return ret
    }, {} as Record<string, { var: VariableSaveForm, index: number }>)
    importErrorTableData.value = []
    for (let i = 0; i < res.length; i++) {
      const item = res[i]
      item.type = item.type === '模拟量' ? '0' : '1'
      item.storage = item.storage === '存储' ? '1' : '0'
      item.show = item.show === '展示' ? '1' : '0'
      item.control = item.control === '可写' ? '1' : '0'
      // 如果address相同
      item.id = vbVariableDTOSDic[item.address]?.var.id
      setSaveForm(new VariableSaveForm(item), vbVariableDTOSDic[item.address]?.index)
      try {
        await submitSaveFormHandle(false)
      } catch (e) {
        try {
          const errList = Object.values(e).flat(2)
          console.log(e, errList)
          importErrorTableData.value.push({
            rowIndex: i + 2,
            errorMsg: errList.map(item => item.message).join('，')
          })
        } catch (e) {}
      }
    }
    if (importErrorTableData.value.length) {
      importDialogModel.value = true
    } else {
      ElMessage.success('导入成功，已更新列表')
    }
  })
}

// 导出
function exportExcelTableData () {
  const sheetData = [['序号', '变量名称[必填]', '变量地址[必填]', '数据类型[必填]（模拟量/开关量）', '变量单位', '数据修正', '历史存储（存储/不存储）', '是否展示（展示/不展示）', '是否控制（只读/可写）']]
  variableModelSaveForm.value.vbVariableDTOS.forEach((item, index) => {
    sheetData.push([
      (index + 1).toString(),
      item.name,
      item.address,
      item.type === '0' ? '模拟量' : '开关量',
      item.unit,
      item.formula,
      item.storage === '0' ? '不存储' : '存储',
      item.show === '0' ? '不展示' : '展示',
      item.control === '0' ? '只读' : '可写'
    ])
  })
  XLSXUtil.exportXlSXFileByArray(sheetData, variableModelSaveForm.value.modelName + '.xlsx')
}
// endregion

// region TODO 导入失败提醒
const importDialogModel = shallowRef(false)
const importErrorTableData = shallowRef<{
  rowIndex: number, errorMsg: string
}[]>([])
// endregion

// region TODO 网关生成的简易变量
function loadGatewayVariable () {
  const _dv = routeParams.defaultValue
  variableModelSaveForm.value.modelName ||= _dv.name
  const vbVariableDTOS = variableModelSaveForm.value.vbVariableDTOS || []
  const sbVarSetDic = new Set(vbVariableDTOS.map((item) => item.address))
  let addCount = 0
  _dv.address.forEach((item) => {
    if (!sbVarSetDic.has(item)) {
      vbVariableDTOS.push(new VariableSaveForm({
        name: item, address: item
      }))
      addCount++
    }
  })
  variableModelSaveForm.value.vbVariableDTOS = vbVariableDTOS
  ElMessage.success(`已从关网关导入${addCount}条变量`)
  console.log(route.params.defaultValue)
}
// endregion
</script>

<template>
  <div class="layout_view d-flex" style="min-height: 100%">
    <div class="c_card-page w-100">
      <div class="c_card_header c_card-title bor-divider-b">变量配置</div>
      <!--基本表单-->
      <el-form
        ref="variableModelSaveFormRef" :rules="variableModelSaveFormRules" :model="variableModelSaveForm"
        inline
        class="c_form-search pt-16"
      >
        <el-form-item label="模板名称" prop="modelName">
          <el-input v-model="variableModelSaveForm.modelName" :readonly="isReadOnly" placeholder="请输入模板名称" />
        </el-form-item>
      </el-form>
      <!--功能栏-->
      <div v-if="!isReadOnly" class="d-flex justify-content-between">
        <div>
          <el-dropdown split-button type="primary" :icon="Plus as any" @click="showSaveFormDrawer()">
            添加变量
            <template #dropdown>
              <el-dropdown-menu>
                <el-dropdown-item @click="showDifferenceValueVariableDrawer()">添加差值变量</el-dropdown-item>
                <el-dropdown-item @click="showComputeVariableDrawer()">添加计算变量</el-dropdown-item>
              </el-dropdown-menu>
            </template>
          </el-dropdown>
          <!--<el-button type="primary" :icon="Plus as any" @click="showSaveFormDrawer()">添加变量</el-button>-->
          <el-button type="primary" class="ml-12" @click="isOpenSort ? closeSort() : openSort()">{{ isOpenSort ? '关闭排序' : '排序' }}</el-button>
          <el-button type="danger" @click="batchDelVariableItem()">批量删除</el-button>
        </div>
        <div class="d-flex">
          <!--JSON-->
          <el-dropdown trigger="click">
            <el-button type="warning">
              JSON<el-icon class="ml-2"><ArrowDown /></el-icon>
            </el-button>
            <template #dropdown>
              <el-dropdown-menu>
                <el-dropdown-item>
                  <yk-upload-file v-model="uploadFile" is-none accept="json" @change="loadTableData">导入配置</yk-upload-file>
                </el-dropdown-item>
                <el-dropdown-item @click="exportTableData">导出配置</el-dropdown-item>
              </el-dropdown-menu>
            </template>
          </el-dropdown>
          <!--Excel-->
          <el-dropdown trigger="click">
            <el-button type="success" class="ml-12">
              <span>Excel</span>
              <el-popover placement="top-start" content="仅支持基本字段导出编辑">
                <template #reference>
                  <el-icon class="ml-2"><InfoFilled /></el-icon>
                </template>
              </el-popover>
              <el-icon class="ml-2"><ArrowDown /></el-icon>
            </el-button>
            <template #dropdown>
              <el-dropdown-menu>
                <el-dropdown-item>
                  <yk-upload-file v-model="uploadExcelFile" is-none @change="loadExcelTableData">导入配置</yk-upload-file>
                </el-dropdown-item>
                <el-dropdown-item @click="exportExcelTableData">导出配置</el-dropdown-item>
              </el-dropdown-menu>
            </template>
          </el-dropdown>
        </div>
      </div>
      <!--表格-->
      <el-table ref="tableDataRef" class="mt-16 c_table-page w-100" stripe :data="variableModelSaveForm.vbVariableDTOS">
        <el-table-column v-if="!isReadOnly" type="selection" />
        <el-table-column label="序号" type="index" width="80" />
        <el-table-column v-if="isOpenSort" label="排序" type="index" width="80">
          <template #default="scope">
            <el-input-number
              v-model="sortTempData[scope.$index]"
              size="small" class="el-c-input-pure w-100" :step="1"
              :min="1" @keyup.enter="sortBlurHandle(scope.$index)"
              @blur="sortBlurHandle(scope.$index)"
            />
          </template>
        </el-table-column>
        <yk-table-column label="变量名称" prop="name" />
        <yk-table-column label="变量地址">
          <template #default="scope">{{ scope.row.dataType === '0' ? scope.row.address : '/' }}</template>
        </yk-table-column>
        <yk-table-column label="变量类型">
          <template #default="scope">{{ ['普通变量', '差值变量', '计算变量'][scope.row.dataType] }}</template>
        </yk-table-column>
        <yk-table-column label="数据类型">
          <template #default="scope">{{ { 0: '模拟量', 1: '开关量' }[scope.row.type] }}</template>
        </yk-table-column>
        <yk-table-column label="变量单位" prop="unit" />
        <yk-table-column label="数据修正" prop="formula" />
        <yk-table-column label="历史存储">
          <template #default="scope">{{ scope.row.storage === '1' ? '存储' : '不存储' }}</template>
        </yk-table-column>
        <yk-table-column label="是否展示">
          <template #default="scope">{{ scope.row.show === '1' ? '展示' : '不展示' }}</template>
        </yk-table-column>
        <yk-table-column label="是否控制">
          <template #default="scope">{{ scope.row.control === '0' ? '只读' : '可写' }}</template>
        </yk-table-column>
        <el-table-column label="操作" width="250px">
          <template #default="scope">
            <div class="c_table-operation">
              <el-link v-if="isReadOnly" type="primary" size="small" @click="openSaveFormDrawerGeneral(scope.row, scope.$index)">查看</el-link>
              <template v-else>
                <el-link type="primary" size="small" @click="openSaveFormDrawerGeneral(scope.row, scope.$index)">编辑</el-link>
                <el-link type="danger" size="small" @click="delVariableItem(scope.$index)">删除</el-link>
              </template>
            </div>
          </template>
        </el-table-column>
      </el-table>
      <!--保存-->
      <div style="margin-top: 60px">
        <el-affix target=".c_table-page" position="bottom" :offset="0">
          <div class="c_affix-bg-white text-center c_form__submit-btn">
            <el-button type="primary" plain @click="closeAndBack">取消</el-button>
            <el-button v-if="!isReadOnly" type="primary" @click="submitVariableModelSaveFormHandle">保存</el-button>
          </div>
        </el-affix>
      </div>
    </div>
    <el-drawer
      v-model="saveFormDrawerModel"
      :modal="!isLoadSaveFormRef"
      class="c_drawer-default"
      :title="isReadOnly ? '查看变量' : ObjectUtil.isNotEmpty(editTableItemIndex) ? '编辑变量' : '添加变量'" :size="440" :close-on-click-modal="false"
    >
      <el-form
        ref="saveFormRef" :model="saveForm" label-width="100px"
        :rules="saveFormRules"
        :disabled="isReadOnly"
      >
        <!--通用信息-->
        <el-form-item label="变量类型" prop="type">
          <el-radio-group v-model="saveForm.type">
            <el-radio label="0">模拟量</el-radio>
            <el-radio label="1">开关量</el-radio>
          </el-radio-group>
        </el-form-item>
        <el-form-item label="变量名称" prop="name">
          <el-input v-model.trim="saveForm.name" placeholder="请输入变量名称" :maxlength="12" show-word-limit />
        </el-form-item>
        <el-form-item label="变量地址" prop="address">
          <el-input v-model.trim="saveForm.address" placeholder="请输入变量地址" />
        </el-form-item>

        <!--开关量信息-->
        <template v-if="saveForm.type === '1'">
          <el-form-item label="代表状态" prop="indicatesStatus">
            <div ref="positionStickyRef" class="bor-divider px-16 pt-16 w-100 overflow-auto" style="max-height: 400px;">
              <div v-for="(item, index) in saveForm.indicatesStatus" :key="index" class="d-flex-center mb-3">
                <el-input-number v-model="item.statusName" class="el-c-input-plain" controls-position="right" />
                <el-input v-model.trim="item.statusValue" class="mx-8" />
                <el-color-picker v-model="item.colour" />
                <el-icon v-if="saveForm.indicatesStatus.length > 2" :size="16" class="color-danger ml-8 cursor-pointer" @click="delIndicatesStatusItem(index)"><Delete /></el-icon>
              </div>
              <div class="position-sticky w-100 bg-color-white pb-16 pt-8" style="bottom: 0;z-index: 2;">
                <el-button type="primary" :icon="Plus as any" plain @click="addIndicatesStatusItem">添加一项</el-button>
              </div>
            </div>
          </el-form-item>
          <el-form-item label="是否复位" prop="reset">
            <el-radio-group v-model="saveForm.reset">
              <el-radio label="2">需要</el-radio>
              <el-radio label="0">不需要</el-radio>
            </el-radio-group>
          </el-form-item>
          <template v-if="saveForm.reset === '2'">
            <el-form-item label="复位延迟" prop="resetTime">
              <div class="d-flex w-100">
                <el-input-number
                  v-model="saveForm.resetTime" class="el-c-input-plain flex-1 text-left" controls-position="right"
                  :step="1"
                  :min="1"
                />
                <div class="ml-2">秒</div>
              </div>
            </el-form-item>
            <el-form-item label="复位指令" prop="resetCommand">
              <el-input-number v-model="saveForm.resetCommand" class="el-c-input-plain w-100 text-left" controls-position="right" />
            </el-form-item>
          </template>
        </template>

        <!--模拟量信息-->
        <template v-if="saveForm.type === '0'">
          <el-form-item label="变量单位" prop="unit">
            <el-input v-model.trim="saveForm.unit" placeholder="请输入变量单位" />
          </el-form-item>
          <el-form-item label="数据修正" prop="formula">
            <el-input v-model.trim="saveForm.formula" placeholder="请输入数据修正" />
            <p class="c_form-tip">例：a*X+b；X代表变量，a b代表常数；<br>可用符号：+ - * / ( )</p>
          </el-form-item>
          <el-form-item label="保留小数位" prop="decimal">
            <el-select v-model="saveForm.decimal" class="w-100">
              <el-option v-for="(item, index) in 6" :key="item" :label="index" :value="index" />
            </el-select>
          </el-form-item>
          <el-form-item label="最大有效值" prop="readMax">
            <el-input-number v-model="saveForm.readMax" class="el-c-input-pure text-left w-100" />
          </el-form-item>
          <el-form-item label="最小有效值" prop="readMin">
            <el-input-number v-model="saveForm.readMin" class="el-c-input-pure text-left w-100" />
          </el-form-item>
        </template>
        <!--通用信息-->
        <el-form-item label="是否展示" prop="show">
          <el-radio-group v-model="saveForm.show">
            <el-radio label="1">展示</el-radio>
            <el-radio label="0">不展示</el-radio>
          </el-radio-group>
        </el-form-item>
        <el-form-item label="历史存储" prop="storage">
          <el-radio-group v-model="saveForm.storage">
            <el-radio label="1">存储</el-radio>
            <el-radio label="0">不存储</el-radio>
          </el-radio-group>
        </el-form-item>
        <el-form-item label="是否控制" prop="control">
          <el-radio-group v-model="saveForm.control">
            <el-radio label="0">只读</el-radio>
            <el-radio label="1">可写</el-radio>
          </el-radio-group>
        </el-form-item>
        <template v-if="saveForm.type === '0' && saveForm.control === '1'">
          <el-form-item label="可写最大值" prop="writeMax">
            <el-input-number v-model="saveForm.writeMax" class="el-c-input-pure text-left w-100" />
          </el-form-item>
          <el-form-item label="可写最小值" prop="writeMin">
            <el-input-number v-model="saveForm.writeMin" class="el-c-input-pure text-left w-100" />
          </el-form-item>
          <el-form-item label="下发数据修正" prop="writeFormula">
            <el-input v-model.trim="saveForm.writeFormula" placeholder="请输入下发数据修正" />
            <p class="c_form-tip">例：a*X+b；X代表输入值，a b代表常数；<br>可用符号：+ - * / ( )</p>
          </el-form-item>
        </template>
      </el-form>
      <template #footer>
        <div class="c_form__submit-btn">
          <el-button type="primary" plain @click="closeSaveFormDrawer">取消</el-button>
          <el-button-group v-if="ObjectUtil.isNotEmpty(editTableItemIndex)" class="ml-3">
            <el-button type="primary" @click="submitSaveVariableFormGeneral({ to: -1 })">上一项</el-button>
            <el-button type="primary" @click="submitSaveFormHandle()">确定</el-button>
            <el-button type="primary" @click="submitSaveVariableFormGeneral({ to: 1 })">下一项</el-button>
          </el-button-group>
          <template v-else>
            <el-button type="primary" @click="submitSaveFormHandle()">确定</el-button>
            <el-button type="primary" @click="submitSaveFormHandleContinue()">确定并继续</el-button>
          </template>
        </div>
      </template>
    </el-drawer>
    <!--导入失败提醒-->
    <el-dialog
      v-model="importDialogModel" title="导入存在异常" width="550px"
      :close-on-click-modal="false" draggable :modal="false"
    >
      <div style="margin-top: -16px;">
        <p class="fs-16">导入时一些数据存在异常，以下是有存在问题的数据</p>
        <p class="color-danger-alpha-7 mt-1">*注：其余数据已导入，无需重复导入</p>
      </div>
      <el-table :data="importErrorTableData" class="c_table-page mt-16" max-height="500px">
        <el-table-column prop="rowIndex" label="行号" width="100px" />
        <el-table-column prop="errorMsg" label="异常原因" />
      </el-table>
    </el-dialog>
    <!--差值变量-->
    <el-drawer
      v-model="differenceValueVariableDialogModel"
      class="c_drawer-default"
      :size="440" :close-on-click-modal="false"
    >
      <template #header>
        <div class="d-flex-align-center">
          <span>差值变量</span>
          <el-popover
            placement="bottom-start" :width="200" trigger="click"
          >
            差值变量常用于变量中只有累计变量没有瞬时变量，或者累计变量的数据是总累计变量需要根据周期重置累计值的情况使用。
            <template #reference>
              <el-icon class="color-info ml-1"><InfoFilled /></el-icon>
            </template>
          </el-popover>
        </div>
      </template>
      <el-form
        ref="differenceValueSaveFormRef" :model="saveForm" label-width="100px"
        :rules="saveFormRules"
        :disabled="isReadOnly"
      >
        <el-form-item label="源变量" prop="parentAddress">
          <el-select v-model="saveForm.parentAddress" class="w-100">
            <el-option v-for="item in differenceValueVariableList" :key="item.address" :label="item.name" :value="item.address" />
          </el-select>
        </el-form-item>
        <el-form-item label="计算方式" prop="computeType">
          <el-select v-model="saveForm.computeType" class="w-100">
            <el-option value="0" label="周期差值">
              <div class="d-flex-between-center">
                <span>周期差值</span>
                <el-popover
                  placement="right-start" :width="200"
                >
                  周期差值依然会保持原变量累计的特性，但是会根据周期重置累计值，如日累计，会统计当日从早到晚的累计数据，可以通过折线图看出上升趋势
                  <template #reference>
                    <el-icon class="color-info"><InfoFilled /></el-icon>
                  </template>
                </el-popover>
              </div>
            </el-option>
            <el-option value="1" label="实时差值">
              <div class="d-flex-between-center">
                <span>实时差值</span>
                <el-popover
                  placement="right-start" :width="200"
                >
                  实时差值将不再拥有累计的特性，会将两次数据求差，将累计数据转为瞬时数据
                  <template #reference>
                    <el-icon class="color-info"><InfoFilled /></el-icon>
                  </template>
                </el-popover>
              </div>
            </el-option>
          </el-select>
        </el-form-item>
        <el-form-item v-if="saveForm.computeType === '0'" label="周期频率" prop="cycleFrequency">
          <el-select v-model="saveForm.cycleFrequency" class="w-100">
            <el-option value="0" label="日" />
            <el-option value="1" label="周" />
            <el-option value="2" label="月" />
          </el-select>
        </el-form-item>
        <el-form-item label="变量名称" prop="name">
          <el-input v-model.trim="saveForm.name" placeholder="请输入变量名称" :maxlength="12" show-word-limit />
        </el-form-item>
        <!--模拟量信息-->
        <template v-if="saveForm.type === '0'">
          <el-form-item label="变量单位" prop="unit">
            <el-input v-model.trim="saveForm.unit" placeholder="请输入变量单位" />
          </el-form-item>
          <el-form-item label="保留小数位" prop="decimal">
            <el-select v-model="saveForm.decimal" class="w-100">
              <el-option v-for="(item, index) in 6" :key="item" :label="index" :value="index" />
            </el-select>
          </el-form-item>
          <el-form-item label="最大有效值" prop="readMax">
            <el-input-number v-model="saveForm.readMax" class="el-c-input-pure text-left w-100" />
          </el-form-item>
          <el-form-item label="最小有效值" prop="readMin">
            <el-input-number v-model="saveForm.readMin" class="el-c-input-pure text-left w-100" />
          </el-form-item>
        </template>
        <!--通用信息-->
        <el-form-item label="是否展示" prop="show">
          <el-radio-group v-model="saveForm.show">
            <el-radio label="1">展示</el-radio>
            <el-radio label="0">不展示</el-radio>
          </el-radio-group>
        </el-form-item>
        <el-form-item label="历史存储" prop="storage">
          <el-radio-group v-model="saveForm.storage">
            <el-radio label="1">存储</el-radio>
            <el-radio label="0">不存储</el-radio>
          </el-radio-group>
        </el-form-item>
      </el-form>
      <template #footer>
        <div class="c_form__submit-btn">
          <el-button type="primary" plain @click="closeDifferenceValueVariableDrawer">取消</el-button>
          <el-button-group v-if="ObjectUtil.isNotEmpty(editTableItemIndex)" class="ml-3">
            <el-button type="primary" @click="submitSaveVariableFormGeneral( { to: -1 })">上一项</el-button>
            <el-button type="primary" @click="differenceValueSubmitSaveFormHandle()">确定</el-button>
            <el-button type="primary" @click="submitSaveVariableFormGeneral( { to: 1 })">下一项</el-button>
          </el-button-group>
          <template v-else>
            <el-button type="primary" @click="differenceValueSubmitSaveFormHandle()">确定</el-button>
            <!--<el-button type="primary" @click="submitSaveFormHandle(true)">确定并继续</el-button>-->
          </template>
        </div>
      </template>
    </el-drawer>
    <!--计算变量-->
    <el-drawer
      v-model="computeVariableDialogModel"
      class="c_drawer-default"
      :size="440" :close-on-click-modal="false"
    >
      <template #header>
        <div class="d-flex-align-center">
          <span>计算变量</span>
          <el-popover
            placement="bottom-start" :width="200" trigger="click"
          >
            计算变量可对多个变量进行逻辑运算，得到一个新的变量。
            <template #reference>
              <el-icon class="color-info ml-1"><InfoFilled /></el-icon>
            </template>
          </el-popover>
        </div>
      </template>
      <el-form
        ref="computeVariableSaveFormRef" :model="saveForm" label-width="100px"
        :rules="saveFormRules"
        :disabled="isReadOnly"
      >
        <el-form-item label="源变量" prop="source" :rules="computeVariableFormRules.source">
          <el-select
            v-model="computeVariableSource" multiple :multiple-limit="10"
            class="w-100" collapse-tags
            placement="left-start"
          >
            <el-option v-for="item in computeVariableList" :key="item.address" :label="item.name" :value="item.address" />
          </el-select>
          <p class="c_form-tip">最多支持10个源变量</p>
        </el-form-item>
        <el-form-item label="变量字典">
          <div class="bor-base p-1 w-100" style="border-radius: 4px;min-height: 80px;">
            <el-tag
              v-for="(item, index) in computeVariableSourceDicList" :key="item.key" closable
              class="m-1 cursor-pointer"
              @click="computeVariableTagClick(item)" @close="computeVariableCloseTag(index)"
            >
              {{ item.key }}：{{ item.name }}
            </el-tag>
          </div>
        </el-form-item>
        <el-form-item label="计算公式" prop=" " :rules="computeVariableFormRules.formula">
          <el-input ref="computeVariableFormulaRef" v-model.trim="saveForm.formula" placeholder="请输入计算公式" />
          <p class="c_form-tip">例：a*(A+B)；A、B代表变量，a代表常数；<br>可用符号：+ - * / ( )</p>
        </el-form-item>
        <el-form-item label="变量名称" prop="name">
          <el-input v-model.trim="saveForm.name" placeholder="请输入变量名称" :maxlength="12" show-word-limit />
        </el-form-item>
        <!--模拟量信息-->
        <template v-if="saveForm.type === '0'">
          <el-form-item label="变量单位" prop="unit">
            <el-input v-model.trim="saveForm.unit" placeholder="请输入变量单位" />
          </el-form-item>
          <el-form-item label="保留小数位" prop="decimal">
            <el-select v-model="saveForm.decimal" class="w-100">
              <el-option v-for="(item, index) in 6" :key="item" :label="index" :value="index" />
            </el-select>
          </el-form-item>
          <el-form-item label="最大有效值" prop="readMax">
            <el-input-number v-model="saveForm.readMax" class="el-c-input-pure text-left w-100" />
          </el-form-item>
          <el-form-item label="最小有效值" prop="readMin">
            <el-input-number v-model="saveForm.readMin" class="el-c-input-pure text-left w-100" />
          </el-form-item>
        </template>
        <!--通用信息-->
        <el-form-item label="是否展示" prop="show">
          <el-radio-group v-model="saveForm.show">
            <el-radio label="1">展示</el-radio>
            <el-radio label="0">不展示</el-radio>
          </el-radio-group>
        </el-form-item>
        <el-form-item label="历史存储" prop="storage">
          <el-radio-group v-model="saveForm.storage">
            <el-radio label="1">存储</el-radio>
            <el-radio label="0">不存储</el-radio>
          </el-radio-group>
        </el-form-item>
      </el-form>
      <template #footer>
        <div class="c_form__submit-btn">
          <el-button type="primary" plain @click="closeComputeVariableDrawer">取消</el-button>
          <el-button type="primary" @click="computeVariableSubmitSaveFormHandle()">确定</el-button>
        </div>
      </template>
    </el-drawer>
  </div>
</template>

<style scoped lang="scss">
// 表格 - 设备列表
.table__device-list {
  grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
  grid-gap: 16px;
}
</style>
